#include "form_factor.h"

#include "vector3D.h"
#include <cmath>
#include "ray.h"
#include <iostream>

namespace t2c2 {

double Form_Factor::calculate(Patch* _patch_i,Patch* _patch_j , const unsigned int _samples,Scene* _scene,bool _shadow) {
	
	double form_factor;
	double sum = 0.0;
	double area = _patch_j->area();
	
	for(unsigned int i =0; i < _samples; i++) {
		Vector3D sample_i = _patch_i->get_sample_point();
		Vector3D sample_j = _patch_j->get_sample_point();
		
		
		Ray occlusion_test(sample_i,sample_j - sample_i);
		bool occlusion = false;
		if(_shadow == true) {
			for(unsigned int j = 0 ; j < _scene->size_patches(); j++) {
				if(_scene->get_patch(j) == _patch_i || _scene->get_patch(j)->get_id() == _patch_i->get_id()) continue;
				double distance = _scene->get_patch(j)->intersection(occlusion_test);
				if(distance > 0) { 
					occlusion = true;
					break;
				}
			}
		}
		
		if(occlusion) continue;
		else {
			Vector3D r = sample_i - sample_j;
			double distance = r.length();
			
			Vector3D normal_i = _patch_i->get_normal(Vector3D());
			Vector3D normal_j = _patch_j->get_normal(Vector3D());
			
			double cos_teta_i = normal_i.dot_product(-r.normalize());
			double cos_teta_j = normal_j.dot_product(r.normalize());
			
			double g_x_y = (cos_teta_i*cos_teta_j)/(M_PI*distance*distance);
			
			sum += g_x_y;
		}
	}
	
	form_factor = sum*(1.0/_samples)*(area);
	
	return form_factor;
}

}
